%{
#define YYDEBUG 1
#include <string.h>
#include <assert.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <time.h>

#define MONSTER_DATA_FILE ("nhsrc/monst.c")
#define MONSTER_SYMBOL_FILE ("nhsrc/monsym.h")
#define CLASSNAME "MonsterSymbol"
#define CLASSFILE "MonsterSymbol.java"
#define DATE_FORMAT ("%Y/%B/%d\t%T  (%Z %z)")

#define ARRAY_SZ (1024)

char** montypes;
char*  monchars;
int monsym_count;
extern char *optarg;
%}

%union {char c; char* s; int i;}

%token <s> KEY
%token <c> VAL
%token <i> INT
%token THE_END
%token DEFINE
%token MONNAME
%token MISC

%%

input: DEFINE something input {}
| THE_END { YYACCEPT; }
;

something: monster_def {}
| junk {}

monster_def: KEY VAL { 
  asprintf(&(montypes[monsym_count]), "%s", $1);
  monchars[monsym_count] = $2;
  monsym_count++;
};

junk: MONNAME INT {}
| MISC {}
| INT {}
| MISC INT {}

%%
extern int yylineno;
extern char* yytext;
int yyerror(char *s, int lineNumber) {
  fprintf(stderr, "Error: %s at %d: '%s'\n", s, yylineno, yytext);
  return 0;
}

int main(int argc, char** argv) {
	int i = 0;
	char* in_fn = MONSTER_SYMBOL_FILE;
	char* out_fn = CLASSFILE;
	char ch;
	char* datestring = calloc(ARRAY_SZ, sizeof(char));
	FILE* monsym_file;
	FILE* out_file;
	time_t curtime = time((time_t*)0);

	while ((ch = getopt(argc, argv, "o:f:")) != -1) {
		switch (ch) {
		case 'f':
			in_fn = optarg;
			break;
		case 'o':
			out_fn = optarg;
			break;
		case '?':
			printf("Usage: %s -o <outfile> -f <infile>");
			exit(1);
		}
	}

	montypes = calloc(ARRAY_SZ, sizeof(char*));
	monchars = calloc(ARRAY_SZ, sizeof(char));
	monsym_count = 0;

	monsym_file = fopen(in_fn, "r");
	yyrestart(monsym_file);
	yyparse();
	fclose(monsym_file);

	strftime(datestring, ARRAY_SZ, DATE_FORMAT, localtime(&curtime));

	out_file = fopen(out_fn, "w");
	fprintf(out_file, "/**\n* This file automatically generated on %s\n**/\n\n", datestring);
	fprintf(out_file, "package termint.game.monsters;\n\npublic enum %s {\n", CLASSNAME);
	assert(monsym_count > 1);
	fprintf(out_file, "\t%s('%c')", montypes[0], monchars[0]);
	for (i = 1; i < monsym_count; i++) {
		if (monchars[i] == '\\') {
			fprintf(out_file, ",%s('\\\\')", montypes[i]);
		} else {
			fprintf(out_file, ",%s('%c')", montypes[i], monchars[i]);
		}
		if (i%7 == 0) {
			fprintf(out_file, "\n\t");
		}
	}
	fprintf(out_file, ";\n\n\tpublic final char symbol;\n");
	fprintf(out_file, "\tprivate %s(char c) {\n\t\tthis.symbol = c;\n\t}\n", CLASSNAME);
	fprintf(out_file, "}\n");
	fclose(out_file);
	return 0;
}